﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Pigs.Enemies;
using Pigs.Weapons;

namespace pigs
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class City : Level
    {
        SteelBoss boss;
        Boolean bossPresent;
        Boolean bossDead;

        public City(GameSettings set)
            : base(set)
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
            bossPresent = false;
            bossDead = false;
            levelName = "ont";
        }

        /// <summary>
        /// LoadContent images for gameplay
        /// </summary>
        public override void LoadContent()
        {
            wave = new Boolean[50];
            this.loadCommonContent();

            //load mountain
            Texture2D cityObject = content.Load<Texture2D>("levels/city/skyScraper");
            Scenery cityScenery = new Scenery(cityObject, new Vector2(400, viewport.Height - cityObject.Height));
            cityScenery.initialize(-.4f, false);
            collidableBackground.Add(cityScenery);

            cityObject = content.Load<Texture2D>("levels/city/skyscraper2");
            cityScenery = new Scenery(cityObject, new Vector2(750, viewport.Height - cityObject.Height));
            cityScenery.initialize(-.4f, false);
            collidableBackground.Add(cityScenery);

            cityObject = content.Load<Texture2D>("levels/city/skyscraper");
            cityScenery = new Scenery(cityObject, new Vector2(1000, viewport.Height - cityObject.Height));
            cityScenery.initialize(-.4f, false);
            collidableBackground.Add(cityScenery);

            cityObject = content.Load<Texture2D>("levels/city/bridge");
            cityScenery = new Scenery(cityObject, new Vector2(1300, viewport.Height - cityObject.Height));
            cityScenery.initialize(-.4f, false);
            collidableBackground.Add(cityScenery);
            
            //load cloud
            Texture2D cityImage = content.Load<Texture2D>("levels/city/city");
            Scenery city = new Scenery(cityImage, new Vector2(0, 0));
            city.initialize(-0.1f, false);
            background.Add(city);
            
            cityImage = content.Load<Texture2D>("levels/city/cityFlipped");
            city = new Scenery(cityImage, new Vector2(cityImage.Width - 1, 0));
            city.initialize(-0.1f, false);
            background.Add(city);

        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            this.commonUpdate(gameTime, otherScreenHasFocus, coveredByOtherScreen);

            //if game is active add pigs at given times
            if (IsActive)
            {
                if (levelTime > 3000 && !wave[1])
                {
                    addBasic(50, 150);
                    addBasic(150, 100);
                    addBasic(150, 200);
                    addBasic(250, 50);
                    addBasic(250, 150);
                    addBasic(250, 250);
                    addBasic(350, 100);
                    addBasic(350, 200);
                    addBasic(450, 50);
                    addBasic(450, 150);
                    addBasic(450, 250);
                    addBasic(550, 100);
                    addBasic(550, 200);
                    addBasic(650, 50);
                    addBasic(650, 150);
                    addBasic(650, 250);
                    addBasic(750, 100);
                    addBasic(750, 200);
                    addBasic(850, 150);
                    addSuicide(950, 150);
                    wave[1] = true;
                }

                //start wave 0 a single normal pig
                if (levelTime > 10000 && !wave[2])
                {
                    addBunny(50, 400);
                    addBunny(50, 400);
                    addBunny(250, 400);
                    addBunny(250, 400);
                    addBunny(50, 200);
                    addBunny(50, 200);
                    addBunny(250, 200);
                    addBunny(250, 200);
                    wave[2] = true;
                }

                if (levelTime > 15000 && !wave[3])
                {
                    addBasic(50, 150);
                    addBasic(150, 100);
                    addBasic(150, 200);
                    addSuicide(950, 150);
                    wave[3] = true;
                }

                if (levelTime > 20000 && !wave[4])
                {
                    addBasic(50, 150);
                    addBasic(150, 100);
                    addBasic(150, 200);
                    addSuicide(950, 150);
                    wave[4] = true;
                }

                if (levelTime > 23000 && !wave[5])
                {
                    addSuicide(50, 450);
                    addSuicide(150, 400);
                    addSuicide(150, 500);
                    addSuicide(250, 350);
                    addSuicide(250, 550);
                    addSuicide(350, 300);
                    addSuicide(350, 600);
                    addSuicide(450, 250);
                    addSuicide(450, 650);
                    wave[5] = true;
                }

                if (levelTime > 35000 && !wave[6])
                {
                    for (int i = 0; i < 6; i++)
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            addBasic(i * 80, j * 80);
                        }
                    }
                    addSuicide(450, 650);
                    wave[6] = true;
                }

                if (levelTime > 50000 && !wave[7])
                {
                    Texture2D cityObject = content.Load<Texture2D>("levels/city/skydome");
                    Scenery cityScenery = new Scenery(cityObject, new Vector2(viewport.Width + 10, viewport.Height - cityObject.Height));
                    cityScenery.initialize(-.4f, false);
                    collidableBackground.Add(cityScenery);

                    addNinja(50, 50);
                    addNinja(50, 350);
                    addNinja(50, 200);

                    wave[7] = true;
                }

                if (levelTime > 53000 && !wave[8])
                {
                    addSteel(100, 100);
                    wave[8] = true;
                }

                if (levelTime > 63000 && !wave[9])
                {
                    for (int i = 0; i < 6; i++)
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            addBasic(i * 80, j * 80);
                        }
                    }
                    wave[9] = true;
                }

                if (levelTime > 68000 && !wave[10])
                {
                    addSuicide(450, 650);
                    wave[10] = true;
                }

                if (levelTime > 75000 && !wave[11])
                {
                    for (int i = 0; i < 6; i++)
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            addBasic(i * 80, j * 80);
                        }
                    }
                    addMagic(10, 150);

                    wave[11] = true;
                }

                if (levelTime > 83000 && !wave[12])
                {
                    addBasic(80, 230);
                    addBasic(80, 330);
                    addMagic(110, 450);
                    addDrunk(100, 150);
                    addDrunk(100, 350);
                    addNinja(100, 200);
                    addNinja(100, 400);
                    wave[12] = true;
                }

                if (levelTime > 87000 && !wave[13])
                {
                    addBasic(80, 230);
                    addBasic(80, 330);
                    addMagic(110, 450);
                    addDrunk(100, 150);
                    addDrunk(100, 350);
                    addNinja(100, 200);
                    addNinja(100, 400);
                    wave[13] = true;
                }

                if (levelTime > 91000 && !wave[14])
                {
                    addBasic(80, 230);
                    addBasic(80, 330);
                    addMagic(110, 450);
                    addDrunk(100, 150);
                    addDrunk(100, 350);
                    addNinja(100, 200);
                    addNinja(100, 400);
                    wave[14] = true;
                }

                if (levelTime > 93000 && !wave[15])
                {
                    Texture2D cityObject = content.Load<Texture2D>("levels/city/goodday");
                    Scenery cityScenery = new Scenery(cityObject, new Vector2(viewport.Width + 150, 50));
                    cityScenery.initialize(-.4f, true);
                    collidableBackground.Add(cityScenery);

                    cityObject = content.Load<Texture2D>("levels/city/bridge");
                    cityScenery = new Scenery(cityObject, new Vector2(viewport.Width + 10, viewport.Height - cityObject.Height));
                    cityScenery.initialize(-.4f, false);
                    collidableBackground.Add(cityScenery);

                    addBunny(50, 400);
                    addBunny(50, 400);
                    addBunny(250, 400);
                    addBunny(250, 400);
                    addBunny(50, 200);
                    addBunny(50, 200);
                    addBunny(250, 200);
                    addBunny(250, 200);
                    addNinja(100, 200);
                    addNinja(100, 400);
                    wave[15] = true;
                }

                if (levelTime > 98000 && !wave[16])
                {
                    addBasic(50, 150);
                    addBasic(150, 100);
                    addBasic(150, 200);
                    addSuicide(950, 150);
                    wave[16] = true;
                }

                if (levelTime > 102000 && !wave[17])
                {
                    addBasic(50, 150);
                    addBasic(50, 100);
                    addBasic(50, 200);
                    addSuicide(950, 150);
                    wave[17] = true;
                }

                if (levelTime > 105000 && !wave[18])
                {
                    addMagic(20, 150);
                    addMagic(20, 350);
                    wave[18] = true;
                }

                if (levelTime > 106000 && !wave[19])
                {
                    addDrunk(20, 250);
                    addDrunk(20, 450);
                    wave[19] = true;
                }

                if (levelTime > 108000 && !wave[20])
                {
                    addBunny(120, 250);
                    addBunny(120, 450);
                    wave[20] = true;
                }

                if (levelTime > 109000 && !wave[21])
                {
                    addNinja(120, 250);
                    addNinja(120, 450);
                    wave[21] = true;
                }

                if (levelTime > 110000 && !wave[22])
                {
                    addLeader(120, 350);
                    addSteel(120, 450);
                    wave[22] = true;
                }

                if (levelTime > 130000 && !wave[23])
                {
                    foreach (Player p in players){
                        if(p.alive)
                        {
                            applyRumble(p, .2f, 0f, 5000);
                        }
                    }
                    Texture2D steelBossText = content.Load<Texture2D>("enemies/steelBoss");
                    Texture2D flames = content.Load<Texture2D>("weapons/fireball");
                    boss = new SteelBoss(steelBossText, new Vector2(viewport.Width + 10, 350), ScreenManager.GraphicsDevice, viewport.Width, flames);
                    this.updateBackgrounds = false;
                    bossPresent = true;
                    wave[23] = true;
                }

                //if boss pig is on the screen update him and check collisions
                if (bossPresent)
                {
                    boss.Update();
                    checkBossCollisions(gameTime);
                }

                if (bossDead && pigs.Count == 0)
                {
                    doEndGame(true);
                }
            }


            //tile the background clouds
            if (((int)background.Last().rectangle.Right) < (viewport.Width + 100))
            {
                Texture2D cityImage = content.Load<Texture2D>("levels/city/city");
                Scenery city = new Scenery(cityImage, new Vector2((int)background.Last().rectangle.Right - 5, 0));
                city.initialize(-0.1f, false);
                background.Add(city);

                cityImage = content.Load<Texture2D>("levels/city/cityFlipped");
                city = new Scenery(cityImage, new Vector2((int)background.Last().rectangle.Right - 1, 0));
                city.initialize(-0.1f, false);
                background.Add(city);
            }
        }

        /// <summary>
        /// check if the boss is colliding with the players
        /// the players bullets and other pigs
        /// </summary>
        void checkBossCollisions(GameTime gameTime)
        {
            foreach (Player p in players)
            {
                if (p.active)
                {
                    if (p.checkCollision(boss)) p.health = -1;
                    p.notHit = false;
                    destroyPlayer(p, gameTime);
                    foreach (Flame f in boss.flames)
                    {
                        if (f.checkCollision(p))
                        {
                            p.applyDamage(f.damage);
                            applyRumble(p, 0.4f, 0, 500);
                        }
                    }
                }
                foreach (Bullet b in p.bullets)
                {
                    if (b.checkCollision(boss)) b.Reflect();
                }
                foreach (Flame f in p.flames)
                {
                    if (f.checkCollision(boss)) f.active = false;
                }
            }
            foreach (Pig p in pigs)
            {
                if (p.checkCollision(boss))
                {
                    //if the pig hitting it is a suicide pig decrease health
                    if (p.ID.Equals("suicide")) boss.health -= 10;
                    p.active = false;
                    playSound(explosionSound);
                    Explosion e = new Explosion(explosionTexture, p.center(), 1);
                    explosions.Add(e);
                }
            }
            // add new pigs
            if (pigs.Count < 3 && levelTime > 150000)
            {
                addBasic(100, 50);
                addBasic(100, 500);
                if (rand.Next(1, 3) == 1) addSuicide(150, 500);
                else addSuicide(150, 150);
            }

            //check health of boss
            if (boss.health <= 0)
            {
                getLowestPlayer().score += 10000;
                bossDead = true;
                boss.active = false;
                bossPresent = false;
                playSound(explosionSound);
                Explosion e = new Explosion(explosionTexture, boss.center(), 3);
                explosions.Add(e);
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Draw(GameTime gameTime)
        {
            this.commonDraw(gameTime);
            if (bossPresent && !bossDead)
            {
                boss.Draw(spriteBatch);
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
